package com.cskaoyan.javase._0abstract._1basic;

/**
 * 抽象类的定义:
 * 在继承体系中，从祖先类开始，随着一个个子类的定义，子类变得越来越具体，
 * 而祖先类则更具有一般性和抽象性。
 * 在这种情况下，为了体现祖先类在设计上的抽象性，
 * 我们只将该类作为派生其他类的父类，而不能创建对象实例。
 * 这个时候，这样的类，我们称之为抽象类。
 *
 * 总结: 抽象类是作为继承层次中,顶层祖先类的.
 *      定义抽象类,一般要求这个类是作为继承层次中的祖先类,不要滥用抽象类.
 *
 * 自此，我们已经引入了抽象类的概念。接下来，我们重点来研究一个抽象类的特点和使用。
 * 抽象类的特点我们主要从以下角度：
 * [修饰符列表] abstract class 类名{
 *     //类体
 * }
 *      1.抽象类名命名特点
 *          抽象类是作为继承层次中祖先类而存在的,为了体现它的特殊性,它的命名也会稍有不同
 *          当然"大驼峰",英文单词,"见名知意"这些是不变的
 *          实际开发中,一般抽象类会以"Base"或者"Abstract"开头
 *          比如: AbstractPerson,BasePerson,BaseStudent
 *
 *
 *       2.能用哪些修饰符？
 *          可以使用访问权限修饰符(有两种访问级别,和普通class一样)
 *          能不能用final修饰抽象类?
 *          显然是不能的,因为final修饰类表示不能被继承的类,但是抽象类不被继承没有任何意义.
 *          抽象类定义的目的就是为了被继承的.
 *
 *      3.成员特点
 *          普通成员,普通类能够定义的都行.
 *          静态成员,普通类能够定义的都行.
 *
 *          抽象方法
 *              抽象类中可以没有抽象方法吗?
 *              语法上来说,可以没有
 *              但是抽象类中没有抽象方法,那有什么意义呢?
 *              没有意义,抽象类就应该有抽象方法.
 *              有些程序员会把一个类定义为抽象类,来禁止该类创建对象,这合适吗?
 *              这不合时,抽象类是做祖先类的
 *              禁止创建对象,应该私有化构造器
 *
 *              一旦抽象父类中定义抽象方法,那么普通子类中必须实现所有的抽象方法.
 *              抽象方法在这里,就起着"占位符"的作用,
 *              普通类只要继承抽象类,就必须实现类中所有的抽象方法.
 *              抽象方法起着"制定标准和规范"的作用.
 *              实现父类中的抽象方法,本质仍然是方法的重写.
 *
 *      抽象类的子类可以是普通类,普通类必须实现所有抽象方法
 *      抽象类的子类也可以是抽象类,抽象子类中可以不实现抽象方法,也可以选择实现某几个.
 *
 *    4.构造器
 *          抽象类不能new创建对象,那么抽象类有没有构造器呢?
 *          构造器的作用:
 *              1.创建自身对象时,给自身成员变量赋值.(抽象类不行)
 *              2.创建子类对象时,给自身成员变量赋值.(抽象类是可以的)
 *          抽象类的构造器虽然自己不能用,但是可以给子类用
 *          抽象类是有构造器的
 *
 *          判断题: Java中任何一个类都有构造器
 *          这是正确的,任何一个Java类,肯定都有构造器,不管普通类还是抽象类
 *
 *      5.代码块
 *          构造代码块: 有构造器就有构造代码块
 *          静态代码块: 也有
 *          它的使用和普通类一样.
 *
 *  以上,一句话总结抽象类的成员和类中结构特点:
 *          和普通类一模一样,只不过是多一个抽象方法
 *          普通类中存在的结构,抽象类中都存在
 *
 *          思考: 在不考虑创建对象的情况下,直接将一个类声明为抽象类,语法上可以吗?
 *              可以的,语法上没有问题.
 *              因为普通类中存在的,抽象类都有
 *
 * 抽象类的子类可以有两种情况：
 *      1.普通类，普通类继承抽象类，必须实现所有的抽象方法。
 *      2.抽象类，抽象子类不需要实现抽象方法，抽象子类可以自由选择实现（或实现或不实现）。
 *
 * 思考:
 *      开发中,实际工作中,会不会经常定义抽象类呢?
 *      显然是不会的,抽象类是作为顶层祖先类存在的,所以往往只有在项目刚启动时,搭架子时才会需要定义抽象类
 *      工作中,可能经常见抽象类,经常用抽象类,但是很少主动定义.
 *
 * @since 09:46
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Student s = new Student();
        s.test();
        AbstractPerson.testStatic();

        Student s2 = new Student(10, 20, 30);
        System.out.println(s2.a);
        System.out.println(s2.age);

    }
}

// 定义抽象人类
abstract class AbstractPerson {
    int a;
    private int b = 10;
    static int c = 20;
    static final int D = 30;

    {

    }

    static {

    }

    public AbstractPerson(int a, int b) {
        this.a = a;
        this.b = b;
    }

    public AbstractPerson() {
    }

    /*
                抽象类当中为什么要存在实现方法?
                抽象类是作为顶层祖先类而存在的
                如果抽象类的所有子类都有一个方法需要实现
                那么可以在抽象父类给一个实现方法
                用来作为所有子类的默认实现
                子类可以选择直接使用默认实现
                也可以选择重写该实现
             */
    public void test() {
        System.out.println("抽象父类的默认实现");
    }

    public static void testStatic() {
    }

    // 定义抽象方法
    public abstract void testAbstract();

    public abstract void testAbstract2();
}

// Class 'Student' must either be declared abstract or implement abstract method 'testAbstract()' in 'AbstractPerson'
/*
    实现抽象方法有两种方式:
        1.alt + 回车类名报错处(推荐)
        2.类体中用快捷键alt + insert
        3.类体中写父类抽象方法的名字
 */
class Student extends AbstractPerson {
    int age;

    public Student(int a, int b, int age) {
        super(a, b);
        this.age = age;
    }

    public Student(int age) {
        this.age = age;
    }

    public Student() {
    }

    @Override
    public void test() {
        System.out.println("子类自己重写实现!");
    }

    @Override
    public void testAbstract() {
        System.out.println("抽象方法的子类实现1");
    }

    @Override
    public void testAbstract2() {
        System.out.println("抽象方法的子类实现2");
    }


}

abstract class BaseTeacher extends AbstractPerson {

}